\documentclass[11pt] {article}

\title {
  Gedistribueerde Systemen\\
  Plan van Aanpak \\
  De Happy Chatters (Groep 4)
}

\author {
  Rik van der Kooij (6064965) \\
  Fabien Tesselaar (6131085) \\
  Martijn van der Veen (5964008) \\
  Gijs van der Voort (6191053) \\
}

\date {\today}

\begin {document}

\maketitle

% Verberg pagina nummering op voorblad
\thispagestyle {empty}

\newpage

\section*{Inleiding}
% Inleiding met probleembeschrijving.
Al in de oudheid is het nuttig gebleken te communiceren. Voor de jacht, machtsgewin, wiskundige problemen of puur voor de lol. Communiceren is het met elkaar spreken en naar de andere luisteren. We willen voor deze opdracht een chat systeem maken, zodat mensen van over de hele wereld met elkaar kunnen communiceren en misschien worden er nog wat wiskundige problemen opgelost! Om een degelijk communicatie-platform op te zetten maken wij gebruik van gedistribueerde systemen.

Een gedistribueerd systeem maakt het mogelijk om taken op meerdere computers of dergelijke apparaten uit te voeren. Het idee hierachter is niet alleen extra rekenkracht, ook robuustheid. Verbreekt de verbinding met een apparaat per ongeluk (of met opzet, maar hopelijk niet!) in ons netwerk, dan kunnen we het opvangen. De taken die niet zijn uitgevoerd weer herverdelen en zorgen dat niemand er echt last van heeft.
Zo maken we een gebruiksvriendelijk chat systeem, dat ook nog snel is. Dit omdat niet elke gebruiker met \'e\'en enkele server hoeft te communiceren, maar wij de druk kunnen verdelen over ons gedistribueerd systeem.

\newpage

\tableofcontents

\newpage

\section {Implementatiekeuze}
% Implementatiekeuze (welke taal, platform, waarom, is het stabiel, is het robuust, wat zijn voordelen, nadelen, heb je meerdere opties overwogen?)
Voor de implementatie is gekozen voor de programmeertaal Python (versie 2.5+). Python is platformonafhankelijk en draait daarom op Linux, Mac OS X en Windows. Omdat onder de teamleden alledrie deze besturingssystemen voorkomen is het belangrijk dat alle code onder deze platformen werkt. Bij alle te gebruiken functies moet dus worden nagegaan of het onder deze drie systemen werkt. De UvA-computer ondersteunen python 2.5, dus ook met deze wat oude versie moet rekening gehouden worden.

% deze sectie is volstrekt niet nodig, maar volgens mij wel leuk
% (en misschien haalt het Roy en Dick over Erlang aan de toegestane talen toe te voegen ;-) )
Hoewel het niet tot de mogelijkheden behoorde, zou de taal Erlang een interessante optie kunnen zijn door de ingebouwde ondersteuning voor gedistribueerde systemen. Het feit dat het wereldwijde Facebook-chatsysteem op Erlang draait toont aan dat het mogelijkheden biedt voor een stabiel gedistribueerd chatsysteem. Dat geen van de vier teamleden Erlang kan, is dan slechts een kleine drempel naar wereldfaam.

De ervaring leert dat het werken in C en in enige mate ook C++ (zeker in grotere projecten) voor extra programmeerwerk zorgt door geheugenmanagement en de enigszins primitieve mogelijkheden (zeker in C dat niet Objectgeori\"enteerd is). In Java en Python zitten meer mogelijkheden in de taal(syntax) ingebouwd. Daarnaast hebben beide talen behoorlijk uitgebreide libraries. Beide programmeertalen draaien op een virtuele machine waardoor extra controles kunnen worden uitgevoerd en het geheel stabieler, maar iets langzamer, is. Bovendien is goede error-handling aanwezig in de taal en zijn eventueel ontstane run-time errors voorzien van een duidelijke traceback.

Programma's geschreven in Python lijken over het algemeen compacter dan programma's geschreven in Java. Bovendien biedt Python constructies die in Java niet mogelijk zijn, zoals een interactieve shell, snelle testfuncties zonder objectgeori\"enteerde overhead, en lambda-calculus. Programma's geschreven in Python zijn mede hierdoor snel geschreven, op een hoog level te lezen en makkelijk aan te passen en te debuggen. Wel moet er enigszins op worden gelet dat in een groot project als dit netjes wordt geprogrammeerd, liefst objectgeori\"enteerd, en de code getest op de verschillende besturingssystemen en Pythonversies.

\section {Analyse van protocol}
% Analyse van het protocol (lijkt het consistent, zijn er onduidelijkheden, zie je problemen, kan het beter, in hoeverre kun je het gemakkelijk uitbreiden, wat zou je kunnen uitbreiden, etc)

\subsection {Protocol}
De server heeft twee bijzondere acties waarbij iets bijzonders moet gebeuren, namelijk het aanmelden in het netwerk (bij opstarten) en het afmelden in het netwerk (na een 700 bericht van een beheerder) waarbij de server moet stoppen. In alle andere gevallen reageert de server slechts op een inkomend pakket met het uitsturen van andere pakketten. Deze input/output-relaties zijn vrij eenvoudig te implementeren. Wel moet hier en daar gecontroleerd worden op time-outs (het niet op tijd reageren op een verstuurd bericht), waardoor er moet worden bijgehouden op welke berichten nog wordt gewacht.

De reactie op een Ping (140) is een Pong (150). Ontvangen berichten van een verbonden client (200/210) of van een andere server (300/310) worden bij bestemming \#all naar alle verbonden clients en servers gestuurd, en bij een specifieke bestemming ofwel naar de directe client (indien aan deze server verbonden), ofwel naar de dichtstbijzijnde server in het pad naar de client. Bij een 700 (stop server) wordt de server afgesloten.

Enkele uitgewerkte (ingewikkeldere) delen van het protocol volgen. Om de diagrammen simpel te houden gaan we voor de diagrammen van een foutloze (error-vrije) communicatie uit. Ping en enkele andere berichten verwachten een antwoord binnen 2 seconden. Dit is niet expliciet opgenomen in het diagram (zoals gezegd gaan ze uit van foutloze communicatie).

\subsubsection {Client (direct) Connects}

\begin{figure}
  \centering
  \includegraphics[width=\textwidth]{img/Protocol_connect_client}
  \caption{Client maakt verbinding met onze server}
\end{figure}

Een client meldt zich aan. De server controleert of de naam uniek is. Als dat het geval is wordt een bevestiging teruggestuurd en krijgt de client een lijst met de namen van alle verbonden clients in het systeem. Wat ons onduidelijk is, is hoe de andere servers en clients nu te horen krijgen dat er een nieuwe client is, en waar die zich bevindt. Als de naam al bestaat wordt een 130 (verbinding verbroken) en een 510 (registratie mislukt) gestuurd.

\subsubsection {Change Client Name}

\begin{figure}
  \centering
  \includegraphics[width=1\textwidth]{img/Protocol_change_client_name}
  \caption{Client verandert naam}
\end{figure}

Als de voorgestelde nieuwe naam al bestaat binnen het netwerk, wordt een 530 (naamwijziging mislukt) teruggestuurd.

Als de client aan een andere server dan de onze verbonden is, komt slechts de 170 binnen. De server wijzigt de naam intern, en stuurt het bericht naar alle verbonden clients en servers behalve de server waar het vandaan kwam (het doorsturen naar de andere servers staat overigens niet in het protocol, maar veronderstellen we).

\subsubsection {Server Connects, Servers Regroup}

\begin{figure}
  \centering
  \includegraphics[width=1\textwidth]{img/Protocol_connect_server}
  \caption{Server maakt verbinding}
\end{figure}

Als de server opstart zijn alleen de eerste vier stappen in het protocol nodig (er zijn immers nog geen clients of child-servers met de server verbonden). Bij een hergroepeer-bericht (604) van de Control Server waarbij de uitgevallen server de parent was van deze server, worden de eerste twee stappen in dit protocol overgeslagen en bepaalt de server zijn parent uit het bericht van de Control Server. Vermoedelijk kreeg de Control Server hieraan voorafgaand eenn 603 bericht (Peerverbinding verbroken) van een met de uitgevallen server verbonden server.

Wat hier onduidelijk is, is hoe nu voor elke server in het huidige netwerk wordt bepaald wat de eerste hop is onderweg naar die server. De beschrijving vindt zo'n lijst essentieel. Volgens ons is het echter overbodig; zie de opmerkingen in de laatste sectie.


\subsection {Uitbreidingen}
We zien mogelijkheden voor uitbreidingen op twee niveaus. Binnen de typenummers zijn nummer 701-799 vrij voor eigen uitbreiding. In die range kunnen de nodige extra pakketten worden gedefinieerd welke tussen servers (die deze uitbreiding ondersteunen) kunnen worden uitgewisseld. Alle servers moeten dan berichten van een onbekend type negeren. Hiermee kunnen bijvoorbeeld lijsten clients, geschiedenis van connecties of instellingen worden uitgewisseld.

Op het niveau van de clients kan ook het een en ander worden uitgebreid. Het bericht kan bijvoorbeeld bij client A worden versleuteld, via het protocol worden verzonden en bij client B (op tekstniveau) worden ontcijferd voordat het wordt getoond. Zo kan je bijvoorbeeld ook plaatjes verzenden: eerst het plaatje omzetten in \emph{plaatjetag} + een (leesbare) string tekst afgeleid aan de bits in het plaatje, dan verzenden, en client B interpreteert het als een deel van een plaatje als het bericht begint met \emph{plaatjetag}. Als client B een uitbreiding als dit niet ondersteunt ziet de gebruiker troep, maar aanpassing van de servers is hierbij niet nodig. Er kan eerst een tekstbericht worden verzonden (bijvoorbeeld 'Ondersteunt jouw client plaatjes?') dat een ondersteunende client niet toont maar met een ander vooraf gedefinieerd antwoord beantwoord. Een client die van niks weet toont alleen het bericht, waarna client A na een time-out concludeert dat hij beter geen plaatjes kan sturen.

Natuurlijk kunnen dit soort berichten ook als nieuwe pakketten worden gedefinieerd, lijkend op 200 en 210, met eventueel volgnummers.


\subsection {Netwerktopologie}
% Geef ook een schema (plaatje) van de netwerk topologie, welke verbindingen zijn er, wat gebeurt er over/met die verbindingen?
De topologie van het netwerk is getoond in Figuur 4.

\begin{figure}
  \centering
  \includegraphics[width=1.2\textwidth]{img/netwerk-topologie}
  \caption{Netwerktopologie}
\end{figure}

\section {Schema software}
% Schema van je te schrijven software. Welke componenten zijn er, hoe werken deze samen, hoe is alles georganiseerd?

\subsection {Server}

\begin{itemize}
\item Opzetten verbinding (zie protocol-aanroep)
\item Zenden pakketten (maken pakket met data adhv protocol, zenden naar goede ip+port)
\item Loop die luistert voor inkomende pakketjes
\end{itemize}

\subsection {Protocol}

\begin{itemize}
\item handig om los te koppelen van server?
\item Opzetten verbinding (connectie met control server, koppelen aan boom)
\item Response (bij bepaald inputpakket bepalen wat naar clients, wat naar servers, wat naar control te zenden)
\item Afsluiten
\end{itemize}

Daarnaast moet nagedacht worden over de verschillende time-outs die kunnen optreden (geen antwoord na 2 seconden, 30 seconden niets van server of client gehoord). De server wacht op binnenkomende pakketten, maar moet ondertussen ook de time-outs in de gaten houden. Als een pakket wordt verwerkt, moet tegelijkertijd worden geluisterd naar nieuwe berichten. Het ligt dus voor de hand het hierboven geschetste systeem uit te breiden met threads, bijvoorbeeld een aparte thread voor de luisterende socket.

\section {Verdeling groep}
% Verdeling binnen de groep (Welk groepslid gaat in eerste instantie wat doen? Hoe is de verdeling, ga je samen werken aan het zelfde, of verdeel je het werk? Hoe zorg je dat alle files consistent blijven? Wanneer speek je af om alles door te nemen?, Wat als iemand ziek wordt, Wat als iemand niet goe meewerkt in het team?)

\begin{itemize}
  \item Leer Python: Rik, Fabi\"en, Gijs
  \item Code:
  \begin{itemize}
    \item Framework: Martijn
    \item Loop met luisterende socket: Rik
    \item Zenden van pakketjes: Fabi\"en
    \item Protocol:
    \begin{itemize}
      \item Opstarten server: Gijs
      \item Afsluiten server: Gijs
      \item Client-server communication: Martijn
      \item Pakketten van andere servers: Rik
    \end{itemize}
  \end{itemize}
  \item Public Relations (mailtjes enzo, in de gaten houden deadlines): Gijs
  \item Verslagen: Allen (eigen deel implementatie)
\end{itemize}


\section {Tijdsplanning}
% Tijdsplanning (wat is wanneer af)
\begin{tabular}{l | l}
  Wat             & Af \\ \hline
  Opzetten project, repository en leren Python    & Week 13 \\
  Plan van Aanpak                                 & Week 13, 14 \\
  Opzetten framework                              & Week 14 \\
  Socketverbinding, begin protocol                & Week 15 \\
  Protocol af, evt. multithreaded maken           & Week 16 \\ % Martijn op reis, skypen!
  Begin verslag                                   & Week 16 \\
  Testen server, debuggen                         & Week 17 \\
  Afmaken server                                  & Week 18 \\
  Afmaken verslag                                 & Week 19, 20 \\
  Gezamenlijk testen, vuurwerk en bier            & Week 20
\end{tabular}

\section {Aanpassingen}
De keuze voor UDP is leuk, maar zorgt wel voor extra werk door het wachten op pakketten die (indirect) bevestigen dan pakketten van onze server zijn aangekomen. Naar onze mening geeft het dus nadelen. Het chatsysteem is geen real time applicatie dus het iets langzamer TCP/IP zou geen probleem moeten zijn. Daarbij mogen pakketten niet verloren gaan. Het overwegen van TCP als protocol is nu laat, maar was volgens ons een handigere keuze geweest. De opdracht lijkt overigens hier en daar nog op TCP gebaseerd, zoals in 5: \emph{'Voor elke direct aan deze server verbonden server tenminste het socketnummer van die server'}.

Zoals vermeld in analyse protocol is het ons onduidelijk hoe nieuwe clients gemeld worden aan de rest van het netwerk. Hoe weten alle servers van het bestaan van de nieuwe client af, en hoe weten ze aan welke server ze vastzitten (als voor clients de server wordt bijgehouden waarmee ze verbonden zijn) of welke server de dichtstbijzijnde server in het pad naar de client is (als voor clients de server wordt bijgehouden die de eerste hop naar de client is)? We verwachtten een pakket in het protocol met 'New Client Connected' dat naar de aangesloten servers en clients gaat. De servers sturen het pakket dan door, waarbij ofwel een ID van de eerste server uit het pakket wordt gehaald, ofwel elke server noteert van welke server het pakket kwam.

Het protocol stelt voor van elke client de server te noteren waarmee hij verbonden is. Ons lijkt het handiger om te noteren wat de eerste hop is voor elke client in het systeem. Beide kunnen met het voorgestelde missende pakket worden achterhaald (eerste server stopt zijn ID in het pakket, of de server noteert van welke server (eerste hop terug) het pakket kwam). De tweede methode scheelt echter het bijhouden van eerste hops naar andere servers; dit is volgens ons overbodig omdat van elke client al bekend is naar welke childserver of parentserver het pakket moet worden gestuurd om door te hoppen naar de uiteindelijke server waarmee de client is verbonden.

\end{document}
